package cn.song;


import cn.hutool.core.date.DateUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.concurrent.CountDownLatch;


@Slf4j
public class ExcelPiLiang {

    private String filePath = "D:\\桌面\\财务使用\\";

    /**
     * 30万数据量 读取Excel 并写入Excel  每五万条数据开启一个线程处理数据
     *
     * @date 2024/06/18
     * @author SongRenShuo
     */
    @Test
    void test001() throws InterruptedException {
        log.info("开始读取Excel");
        ExcelReader reader = ExcelUtil.getReader(filePath + "原始数据.xlsx");
        // 每五万条数据 开启一个线程处理数据
        int size = 50000;
        int count = reader.getRowCount();
        CountDownLatch latch = new CountDownLatch((count - 1) / size);

        for (int i = 1; i < count; i += size) {
            List<List<Object>> rows = reader.read(i, i + size - 1);

            // 开启线程处理数据
            new Thread(() -> {
                String name = Thread.currentThread().getName();
                log.info("线程开始处理数据,当前线程：{},处理数据个数:{},开始时间：{}", name, rows.size(), DateUtil.now());
                try (ExcelWriter writer = ExcelUtil.getWriter(filePath + "执行结果_" + name + ".xlsx")) {

                    writer.writeRow(reader.readRow(0));

                    // 处理数据
                    for (List<Object> row : rows) {
                        // 处理数据逻辑
                        // ...
                        // System.err.println(row);
                        // 一行一行输出
                        writer.writeRow(row);
                    }
                    writer.flush();
                } catch (Exception e) {
                    log.error("线程处理数据异常,当前线程：{},处理数据个数:{}", name, rows.size(), e);
                } finally {
                    // 工作完成，计数器减一
                    latch.countDown();
                    log.info("线程处理数据完成,当前线程：{},处理数据个数:{},结束时间：{}", name, rows.size(), DateUtil.now());
                }
            }).start();
        }

        // 主线程等待所有线程完成
        latch.await();

        log.info("所有线程处理完数据");
    }

}
